home *** CD-ROM | disk | FTP | other *** search
- /*
- ** TC-MENU.C
- **
- ** Turbo C version of James Pinson's Lattice C program PULLDOWN.C
- **
- ** I edited his program to suit my indentation style, cleaned up the
- ** code in a few places, and made adjustments for Turbo C.
- **
- ** Compile with tcc -K tc-menu
- ** or in TC with O/C/C/Default char type...Unsigned
- ** Ignore the three compiler warnings.
- **
- ** If you get snow on your monitor, type in tc-menu s to prevent
- ** the program from using direct screen writes.
- **
- ** -- Scott Houck
- */
-
- #include <stdio.h>
- #include <ctype.h>
- #include <dos.h>
- #include <conio.h>
- #include <mem.h>
-
- #define BLACK 0 /* These are for color cards */
- #define BLUE 1
- #define GREEN 2
- #define CYAN 3
- #define RED 4
- #define MAGENTA 5
- #define BROWN 6
- #define WHITE 7
- #define L_BLUE 9 /* Light-blue foreground only */
- #define L_GREEN 10 /* Light-green foreground only */
- #define YELLOW 14
- #define IWHITE 15 /* Intense-white foreground only */
-
- #define UNDERLINE 1 /* These are for monochrome cards */
- #define NORMAL 7
- #define HI_INTEN 15
- #define REVERSE 112
-
- #define TRUE 1
- #define FALSE 0
-
- unsigned int page; /* extern decl. for functions */
- unsigned int attribute;
- unsigned int mon_type;
- char wrt_meth = 'f';
-
- #define NU_MAIN 5 /* number of main menu options */
- #define NU_SUB 5 /* number of sub menu options */
-
- int menu();
- int pull_down();
- void make_help();
- void make_inst();
- void mono_help();
- void demo();
- void help();
- void gotoxy();
- int wherexy();
- void d_page();
- void win_save();
- int set_color();
- void clear_window();
- void box();
- int what_mon();
- void cls();
- void make_window();
- int cursor();
- void print();
- void dos_prt();
- void fast_write();
- int get_key();
-
-
- struct menu_str /* change this if you need more options */
- {
- char *head;
- char *body[NU_SUB];
- void (*fun1)();
- void (*fun2)();
- void (*fun3)();
- void (*fun4)();
- void (*fun5)();
- };
-
-
- /*-----------*/
- /* M A I N */
- /*-----------*/
-
- main(argc, argv)
- int argc;
- char **argv;
- {
- extern unsigned int page;
- extern unsigned int attribute;
- extern unsigned int mon_type;
-
- int hi_attr, nor_attr;
-
- static struct menu_str m_menu[NU_MAIN] =
- {
- " File ", /* The first menu option */
- " Dir ", /* Menu sub options */
- " Load ",
- " Save ",
- " dElete ",
- " Path ",
- demo, /* The functions each sub-option call */
- demo,
- demo, /* these all call the same fake function */
- demo,
- demo,
-
- " fiNd ", /* The second menu option */
- " All-words ",
- " First-word ",
- "\0",
- "\0", /* space filler for unused option names */
- "\0",
- demo,
- demo,
- 0, /* unused function pointer */
- 0,
- 0,
-
- " Configure ", /* The third option */
- " Modem ",
- " Screen ",
- " Printer ",
- "\0",
- "\0",
- demo,
- demo,
- demo,
- 0,
- 0,
-
- " Output ", /* The fourth menu option */
- " Screen ",
- " Printer ",
- " Disk ",
- " Modem ",
- "\0",
- demo,
- demo,
- demo,
- demo,
- 0,
-
-
- " Help ", /* The fifth option */
- " Instant help (really works) ",
- "\0",
- "\0",
- "\0",
- "\0",
- help,
- 0,
- 0,
- 0,
- 0,
- };
-
-
- /* was a slow write requested? */
- if (tolower(*argv[1]) == 's')
- wrt_meth = 's';
-
- page = 0;
- mon_type = what_mon();
-
- if (mon_type == 1) /* Find out if you have a color card */
- {
- hi_attr = set_color(BLACK, CYAN); /* and set attributes accordingly */
- nor_attr = set_color(WHITE, BLACK);
- }
- else
- {
- hi_attr = REVERSE;
- nor_attr = NORMAL;
- }
-
- attribute = nor_attr;
- cursor(0); /* hide cursor */
- win_save('s');
- cls();
-
- if (mon_type == 1)
- make_help();
-
- make_inst(); /* Show instructions */
-
- menu(m_menu, NU_MAIN, NU_SUB, hi_attr, nor_attr);
-
- win_save('r'); /* restore text display*/
- cursor(1); /* restore cursor */
- }
-
-
- /*-----------*/
- /* M E N U */
- /*-----------*/
-
- int menu(m_menu, nu_main, nu_sub, hi_attr, nor_attr)
- struct menu_str m_menu[];
- int nu_main, nu_sub, hi_attr, nor_attr;
- {
- extern unsigned int page;
- extern unsigned int attribute;
- extern unsigned int mon_type;
-
- int i, j, cur_x, cur_y, cur_opt, found, expert = 1;
- char ch, ext, ltr;
-
- ch = ' ';
- ext = ' ';
- cur_opt = 0;
- found = 0;
-
- if (mon_type == 1)
- attribute = set_color(YELLOW, BLACK);
- else
- attribute = nor_attr;
-
- make_window(1, 1, 78, 1, 1);
-
- for (;;) /* endless loop */
- {
- for (i = 0; i < nu_main; i++)
- {
- j = 0;
- while (ltr = m_menu[i].head[j++])
- {
- if (ch == ltr && ch != ' ')
- {
- found = TRUE;
- cur_opt = i;
- }
- }
- }
- if (ch == 13)
- {
- found = TRUE;
- expert = FALSE;
- }
-
- ch = ' ';
- cur_x = 2;
- cur_y = 2;
-
- for (i = 0; i < nu_main; i++)
- {
- if (i == cur_opt)
- attribute = hi_attr;
- else
- attribute= nor_attr;
- print(cur_x, cur_y, m_menu[i].head);
- cur_x += strlen(m_menu[i].head) + 3;
- }
-
- if (!expert)
- found = TRUE;
-
- if (found)
- {
- ext = pull_down(m_menu, nu_sub, cur_opt); /* pull-down options */
- if (ext == 27)
- expert = TRUE;
- if (ext == 'r' || ext == 'l')
- expert = FALSE;
- if (ext == 'r')
- ++cur_opt;
- if (ext == 'l')
- --cur_opt;
- ch = ' ';
- ext = ' ';
- }
-
- if (!found)
- {
- ch = ' ';
- get_key(&ch, &ext);
- ch = toupper(ch);
- }
-
- if (ch == 27)
- return;
-
- if (ext == 'r' || ext == 'l')
- expert = 0;
- if (ext == 'r')
- ++cur_opt;
- if (ext == 'l')
- --cur_opt;
- if (cur_opt >= nu_main)
- cur_opt = 0;
- if (cur_opt < 0)
- cur_opt = nu_main - 1;
- ext = ' ';
- found = 0;
-
- } /* end for (;;) */
- }
-
-
-
- /*---------------------*/
- /* P U L L _ D O W N */
- /*---------------------*/
-
- int pull_down(m_menu, nu_sub, position)
- struct menu_str m_menu[];
- int position;
- {
- extern unsigned int page;
- extern unsigned int attribute;
- char ch = ' ', ltr;
- int ext = ' ', hi_attr, nor_attr;
- int i, j, tx, ty, start, width, nu_opt, cur_opt = 0, found = FALSE;
-
- nu_opt = nu_sub;
-
- /* nu_sub = number of possible pull-down options */
- /* find out how many are in use */
-
- for (i = 0; i < nu_opt; i++)
- {
- if (m_menu[position].body[i][0] == '\0')
- {
- nu_opt = i;
- break;
- }
- }
-
- if (mon_type == 1)
- {
- hi_attr = set_color(BLACK, CYAN);
- nor_attr = set_color(WHITE, BLACK);
- }
- else
- {
- hi_attr = REVERSE;
- nor_attr = NORMAL;
- }
-
- attribute = nor_attr;
-
- start = 2; /* Figure where to draw pull-down box */
- /* 2 is column to start 1st box */
- /* Add up length of menu heads */
-
- for (i = 0; i < position; i++)
- start += strlen(m_menu[i].head) + 3;
-
- width = 0; /* figure max length of window */
-
- for (i = 0; i < nu_opt; i++)
- if (strlen(m_menu[position].body[i]) > width)
- width = strlen(m_menu[position].body[i]);
-
- /* move box to left if it will spill off right side */
-
- if (start + width + 1 > 80)
- start = 80 - width - 2;
-
- win_save('s');
-
- if (mon_type == 1)
- attribute = set_color(YELLOW, BLACK);
-
- make_window(start++, 3, width, nu_opt, 0); /*make a window */
- attribute = nor_attr;
-
- tx = start; /* reposition for writing */
- ty = 4;
-
- for (;;)
- {
- for (i = 0; i < nu_opt; i++)
- {
- if (i == cur_opt)
- attribute = hi_attr;
- else
- attribute = nor_attr;
- print(tx, ty++, m_menu[position].body[i]);
- }
-
- attribute = nor_attr;
-
- if (found)
- {
- win_save('r'); /* remove box */
-
- /* If you want more than 5 menu options */
- /* change this next switch statement */
-
- switch(cur_opt) /* call function */
- {
- case 0: (*m_menu[position].fun1)(); break;
- case 1: (*m_menu[position].fun2)(); break;
- case 2: (*m_menu[position].fun3)(); break;
- case 3: (*m_menu[position].fun4)(); break;
- case 4: (*m_menu[position].fun5)(); break;
- }
-
- /* found = FALSE; */
- if (kbhit())
- getch(); /* make sure keyboard buffer is clear */
- return(' ');
- }
-
- tx = start;
- ty = 4;
- get_key(&ch, &ext); /* get a character */
- ch = toupper(ch);
- if (ext == 'd')
- ++cur_opt;
- if (ext == 'u')
- --cur_opt;
- if (cur_opt >= nu_opt)
- cur_opt = 0;
- if (cur_opt < 0)
- cur_opt = nu_opt - 1;
-
- if (ch == 13)
- found = TRUE;
-
- for (i = 0; i < nu_opt; i++) /* does it match an option? */
- {
- j = 0;
- while (ltr = m_menu[position].body[i][j++])
- {
- if (ch == ltr)
- {
- cur_opt = i;
- found = TRUE;
- }
- }
- }
-
- if (ext == 'l'|| ext == 'r')
- break;
-
- if (ch == 27) /* EXIT IF ESCAPE KEY */
- {
- ext = ch;
- break;
- }
-
- ext = ' ';
- ch = ' ';
-
- } /* end for (;;) */
-
- win_save('r');
- return (ext);
- }
-
-
- /*---------------------*/
- /* M A K E _ H E L P */
- /*---------------------*/
-
- void make_help()
- {
- extern unsigned int page, attribute;
-
- page = 1;
-
- print( 1, 1, "Hello - This is a sample of an instant help screen.");
- print(10, 5, "This screen was printed to the second page of graphics");
- print(10, 7, "while you were looking at the main menu.");
- print(10, 9, "This help screen can be left undisturbed");
- print(10, 11, "and redisplayed at any time.");
- print( 1, 20, "Please touch any key to return to the main menu.");
-
- page = 0;
- }
-
-
- /*---------------------*/
- /* M A K E _ I N S T */
- /*---------------------*/
-
- void make_inst()
- {
- extern unsigned int attribute;
-
- if (mon_type == 1)
- attribute = set_color(GREEN, BLACK);
- else
- attribute = NORMAL;
-
- print( 1, 4, "INSTRUCTIONS:");
- print( 1, 6, "EXPERT MODE: Select by touching the key which represents each option.");
- print(15, 7, "(the capital letter)");
-
- print( 1, 10, "ASSIST MODE: Pull-down menu by touching 'enter' or a cursor key.");
- print(14, 11, "Select by highlighting with cursor keys- then touch return");
- print(14, 13, "Return to Expert mode by touching 'escape'");
-
- print( 1, 15, "EXIT: Touch 'Escape' while in expert mode.");
- }
-
-
- /*---------------------*/
- /* M O N O _ H E L P */
- /*---------------------*/
-
- void mono_help()
- {
- attribute = NORMAL;
- win_save('s');
-
- clear_window(1, 4, 80, 21);
- print(1, 7, "This is a demonstration of a help screen.");
- print(1, 9, "This text was written by means of direct memory address.");
- print(1, 10, "The original screen has been saved and will be restored ");
- print(1, 11, "when you exit this 'help' screen.");
- print(1, 14, "Please touch any key to continue.");
-
- getch();
- win_save('r');
- }
-
-
- /*-----------*/
- /* D E M O */
- /*-----------*/
-
- void demo()
- {
- win_save('s');
- make_window(20, 10, 40, 5, 1);
-
- print(21, 11, "Put your favorite routine here ");
- print(21, 14, "touch any key to return to menu");
- getch();
-
- win_save('r');
- }
-
-
- /*-----------*/
- /* H E L P */
- /*-----------*/
-
- void help()
- {
- if (mon_type == 1) /* If color card flip page to */
- {
- page = 1; /* Show text else write to current screen */
- d_page();
- getch();
- page = 0;
- d_page();
- }
- else
- mono_help();
- }
-
-
- /* Screen Function Library */
-
- /*
- ** Declare the extern variables page, attribute, and
- ** mon_type (monitor type) in your main program.
- */
-
-
- /*---------------*/
- /* G O T O X Y */
- /*---------------*/
-
- void gotoxy(x, y) /* Puts cursor at x,y position on selected page */
- unsigned int x, y; /* 1,1 is upper left corner */
- {
- extern unsigned int page;
- union REGS regist;
-
- if (x < 1 || x > 80)
- return;
- if (y < 1 || y > 25)
- return;
- --x;
- --y; /* BIOS starts coordinates at 0,0 */
-
- regist.h.ah = 0x02;
- regist.x.dx = (y << 8) | x;
- regist.h.bh = page;
- int86(0x10, ®ist, ®ist);
- }
-
-
- /*-----------------*/
- /* W H E R E X Y */
- /*-----------------*/
-
- int wherexy(x, y) /* Returns the x,y position of cursor */
- int *x, *y;
- {
- extern unsigned int page;
- union REGS regist;
-
- regist.h.ah = 0x03;
- regist.h.bh = page;
- int86(0x10, ®ist, ®ist);
- *x = regist.h.dl + 1;
- *y = regist.h.dh + 1;
- }
-
-
- /*---------------*/
- /* D _ P A G E */
- /*---------------*/
-
- /* Displays the page indicated by extern var page */
- /* Use only with color card */
-
- void d_page()
- {
- extern unsigned int page;
- union REGS regist;
-
- regist.h.ah = 0x05;
- regist.h.al = page;
- int86(0x10, ®ist,®ist);
- }
-
-
- /*-------------------*/
- /* W I N _ S A V E */
- /*-------------------*/
-
- void win_save(action) /* Saves or restores primary */
- int action; /* display screen. */
- { /* (page 0 for color display) */
- extern unsigned int page; /* 's' = save */
- extern unsigned int mon_type; /* 'r' = restore */
- int position; /* Saves cursor position too */
- static int ptr; /* May make snow on CGA */
-
- static struct
- {
- int x;
- int y;
- unsigned int buffer[4000];
- }
- window[2];
-
-
- if (mon_type == 1)
- position = 0xB800; /* Color card */
- else
- position = 0xB000; /* Monochrome */
-
- if (action == 's') /* save */
- {
- if (ptr > 1)
- {
- ptr = 2;
- return;
- }
-
- /*
- ** Note: I used movedata because the peek function is specific
- ** to Lattice C.
- **
- ** peek(position, 0x00, &window[ptr].buffer, 4000);
- **
- ** Also see poke below.
- */
-
- /* save screen */
- movedata(position, 0, _DS, (int)&window[ptr].buffer, 4000);
-
- /* save cursor location */
- wherexy(&window[ptr].x, &window[ptr].y);
- ptr++;
- }
-
- if (action == 'r') /* restore */
- {
- if (ptr < 1)
- {
- ptr = 0;
- return;
- }
- --ptr;
-
- /* poke(position, 0, &window[ptr].buffer, 4000); */
-
- /* restore screen */
- movedata(_DS, (int)&window[ptr].buffer, position, 0, 4000);
-
- /* restore cursor location */
- gotoxy(window[ptr].x, window[ptr].y);
- }
- }
-
-
-
- /*---------------------*/
- /* S E T _ C O L O R */
- /*---------------------*/
-
- /* Call with foreground and background colors. Returns attribute. */
-
- int set_color(foreground, background)
- int foreground,background;
- {
- return (background << 4 | foreground);
- }
-
-
-
- /*---------------------------*/
- /* C L E A R _ W I N D O W */
- /*---------------------------*/
-
- void clear_window(x, y, width, height) /* Call with x,y of upper left */
- unsigned int x, y, width, height; /* corner of window area. */
- { /* Clears down and to right */
- extern unsigned int page; /* for width and height. */
- extern unsigned int attribute; /* Cleared with active attribute */
- union REGS regist; /* Use on displayed page only! */
-
- regist.x.ax = 0x0600;
- regist.h.ch = --y;
- regist.h.cl = --x;
- regist.x.dx = (y + height - 1) << 8 | x + width - 1;
- regist.h.bh = attribute;
- int86(0x10, ®ist, ®ist);
- }
-
-
- /*---------*/
- /* B O X */
- /*---------*/
-
- void box(x, y, width, height, type) /* type 0 = pull-down box */
- int x, y, width, height, type; /* type 1 = regular box */
- {
- int i, u_right, u_left;
- char string[82];
-
- if (type == 0) /* following sets corners */
- {
- u_left = '\xC2';
- u_right = '\xC2';
- }
- else if (type == 1)
- {
- u_left = '\xDA';
- u_right = '\xBF';
- }
-
- string[0] = u_left;
- for (i = 1; i <= width; string[i++] = '\xC4');
- string[i++] = u_right;
- string[i] = '\0';
- print(x, y++, string);
-
- for (i = 0; i < height; i++)
- {
- print(x, y, "\xB3");
- print(x + width + 1, y++, "\xB3");
- }
-
- string[0]='\xC0';
- for(i = 1; i <= width; string[i++] = '\xC4');
- string[i++] = '\xD9';
- string[i] = '\0';
- print(x, y++, string);
- }
-
-
- /*-------------------*/
- /* W H A T _ M O N */
- /*-------------------*/
-
- int what_mon() /* Returns a 1 if color card present, 0 if monochrome */
- {
- return (peekb(0x0040, 0x0049) != 7);
- }
-
-
- /*---------*/
- /* C L S */
- /*---------*/
-
- void cls() /* Same as DOS cls */
- {
- clear_window(1, 1, 80, 25);
- gotoxy(1, 1);
- }
-
-
- /*-------------------------*/
- /* M A K E _ W I N D O W */
- /*-------------------------*/
-
- void make_window(x, y, width, height, type) /* Draws and clears a box */
- unsigned int x, y, width, height, type;
- {
- box(x++, y++, width, height, type); /* Draw box */
- clear_window(x, y, width, height); /* Clear interior */
- }
-
-
- /*---------------*/
- /* C U R S O R */
- /*---------------*/
-
- int cursor(size) /* Sets cursor size */
- int size; /* 0 = no cursor, 1 = normal, 2 = big cursor */
- {
- union REGS regist;
-
- regist.h.ah = 0x01;
-
- if (mon_type == 1 ) /* color */
- {
- if (size == 0)
- regist.x.cx = 0x0F0F;
- else if (size == 1)
- regist.x.cx = 0x0607;
- else if (size == 2)
- regist.x.cx = 0x0107;
- }
- else /* monochrome */
- {
- if (size == 0)
- regist.x.cx = 0x0F0F;
- else if (size == 1)
- regist.x.cx = 0x0C0D;
- else if (size == 2)
- regist.x.cx = 0x010D;
- }
-
- int86(0x10, ®ist, ®ist);
- }
-
-
- /*-------------*/
- /* P R I N T */
- /*-------------*/
-
- void print(x, y, str) /* A switcher - routes to fast_write */
- unsigned int x, y; /* or to dos_prt depending on argv */
- char *str; /* passed to program and stored in */
- { /* extern char wr_meth */
- extern char wrt_meth;
-
- if (wrt_meth == 'f') /* Fast (direct poking) */
- fast_write(x, y, str);
- else if (wrt_meth == 's') /* Slow (DOS method) */
- {
- gotoxy(x, y);
- dos_prt(str);
- }
- }
-
-
- /*-----------------*/ /* Asks DOS to write a string with attribute */
- /* D O S _ P R T */ /* defined. an alternative to fast write in */
- /*-----------------*/ /* that it is "well behaved" (goes through DOS) */
- /* Specify page and set cursor position before */
- void dos_prt(str) /* calling */
- char *str;
- {
- extern unsigned int page, attribute;
- unsigned int x, y;
- union REGS regist;
-
- wherexy(&x, &y);
- while (*str)
- {
- if (x > 80)
- {
- x = 1;
- ++y;
- }
- if (y > 25)
- break;
- gotoxy(x++, y);
- regist.x.bx = (page << 8 | attribute);
- regist.x.cx = 1;
- regist.x.ax = 0x0900 | *str++;
- int86(0x10, ®ist, ®ist);
- }
- gotoxy(x, y); /* put cursor at end of string */
- }
-
-
- /*-----------------------*/
- /* F A S T _ W R I T E */
- /*-----------------------*/
-
- void fast_write(x, y, string) /* Directly pokes string at x,y position */
- int x, y; /* Uses attribute and page. */
- char *string; /* May cause snow on some graphic cards */
- {
- extern unsigned int page;
- extern unsigned int attribute;
- extern unsigned int mon_type; /* Monitor type */
- int position, offset, orig;
-
- if (page <= 3 && page >= 0)
- offset = 4000 * page + 96 * page;
- orig = offset;
- offset += (y-1) * 160 + 2 * (x-1);
- if (mon_type == 0)
- position = 0xB000;
- else
- position = 0xB800;
-
- while (*string)
- {
- pokeb(position, offset, *string++); /* Poke character */
- pokeb(position, offset+1, (char)attribute); /* Poke attribute */
- offset += 2;
- }
- offset -= orig; /* Figure where I am */
- x = (offset % 160) / 2 + 1;
- y = offset / 160 + 1; /* and move cursor */
- gotoxy(x, y);
- }
-
-
- /*-----------------*/
- /* G E T _ K E Y */
- /*-----------------*/
-
- int get_key(ch, ext) /* Read a char */
- char *ch; /* Return character in ch */
- int *ext; /* If it is a function key */
- { /* return following in ext */
- *ch = getch(); /* up-arrow = 'u' */
- if (!*ch) /* down-arrow = 'd' */
- { /* right-arrow = 'r' */
- *ext = getch(); /* left-arrow = 'l' */
- switch (*ext)
- {
- case 'H': *ext = 'u'; break; /* up */
- case 'P': *ext = 'd'; break; /* down */
- case 'M': *ext = 'r'; break; /* right */
- case 'K': *ext = 'l'; break; /* left */
- case 'G': *ext = 'h'; break; /* home */
- case 'O': *ext = 'e'; break; /* end */
- case 'R': *ext = 'I'; break; /* insert */
- case 'S': *ext = 'D'; break; /* delete */
- }
- }
- }